<?php

namespace app\api\controller\mall;

use app\api\model\YaoqingRecords;
use think\Db;
use think\Request;
use think\Validate;
use app\api\model\VolleyDesc as Balance;
use app\api\model\ConfigSystem as Config;
use app\api\model\MallDistribution;
use app\api\model\MallOrderFanli;

class Goods extends CommonMall
{
    // 商品分类
    public function category()
    {
        $page = input('page/d') ? input('page/d') : 1;
        $parent_id = input('parent_id/d') ? input('parent_id/d') : 0;

        // 开始验证
        $validate = new Validate([
            ['page', 'number|>:0', '分页有误|分页有误'],
        ]);

        $data = [
            'page' => $page,
        ];

        if (!$validate->check($data)) {
            exit(json_encode(['err' => $validate->getError()]));
        } else {
            try {
                $data = $this->db->name('mall_category')
                    ->field('id, name, image')
                    ->where(['parent_id' => $parent_id, 'is_hidden' => 0])
                    ->order('sort desc, id desc')
                    ->cache(false)->fetchSql(false)->paginate(10)->toarray();

            } catch (Exception $e) {
                return json(['err' => $e->getMessage()]);
            }

            if ($data['data']) {
                foreach ($data['data'] as $key => $value) {
                    $data['data'][$key]['image'] = $value['image'];
                }
            }

            return json(['ret' => $data]);
        }
    }
    // 商品分类-树状
    public function categoryTree()
    {
        $data = $this->db->name('mall_category')
            ->field('id, name, image, parent_id')
            ->where(['is_hidden' => 0])
            ->order('sort desc, id desc')
            ->select();

        $data = self::toTree($data, 0);
        return $this->pass($data);
    }
    public static function toTree($category, $parent_id)
    {
        $tree = [];
        foreach ($category as $v) {
            if ($v['parent_id'] == $parent_id) {
                $v['children'] = self::toTree($category, $v['id']);
                $tree[] = $v;
            }
        }
        return $tree;
    }
    public function cateids($cate_id, $cate_ids = [])
    {
        $cate_id = is_array($cate_id) ? $cate_id : [$cate_id];
        $col = $this->db->name('mall_category')->where(['parent_id'=>['in', $cate_id]])->column('id');
        if (sizeof($col)) {
            $cate_ids = array_merge($cate_id, $cate_ids);
            return $this->cateids($col, $cate_ids);
        } else {
            $cate_ids = array_merge($cate_id, $cate_ids);
            return $cate_ids;
        }
    }
    public function index()
    {
        $data['slides'] = $this->db->name('slides')
                            ->where(['tid' => 7, 'hide' => 0])
                            ->field('tid,des,create_time,update_time,hide', 'filter')
                            ->order('des desc,id desc')
                            ->select();
        $data['category'] = $this->db->name('mall_category')
                                ->field('id, name, image')
                                ->where(['parent_id' => 0, 'is_hidden' => 0])
                                ->order('sort desc, id desc')
                                ->limit(9)
                                ->select();
        $data['rec_goods'] = $this->goodsListRecommend(false);
        $data['goods'] = $this->goodsList(false);
        return $this->pass($data);
    }

    // 商品列表
    public function goodsList($returnJson = true)
    {
        // 全局安全过滤
        Request::instance()->filter(['strip_tags', 'htmlspecialchars_decode', 'trim']);
        $score = input('score/d', 1);
        $data = [
            'page' => $page = input('page/d') ? input('page/d') : 1,
            'cate_id' => $cate_id = input('cate_id/d'),
            'user_id' => $user_id = input('user_id/d'),
            'keyword' => $keyword = input('keyword'),
            'sales' => $sales = input('sales'),
            'price' => $price = input('price'),
            'visit' => $visit = input('visit'),
        ];

        // 开始验证
        $validate = new Validate([
            ['page', 'number|>:0', '分页有误|分页有误'],
            // ['cate_id', 'number|>:0', '分类有误|分类有误'],
            ['sales', 'in:asc,desc', '销量排序有误'],
            ['price', 'in:asc,desc', '价格排序有误'],
            ['visit', 'in:asc,desc', '浏览量排序有误'],
        ]);

        if (!$validate->check($data)) {
            exit(json_encode(['err' => $validate->getError()]));
        } else {
            $where = [];
            $order = [];
            $where = [];

            // 分类筛选
            if ($cate_id) {
                $where['cate_id'] = ['in', $this->cateids($cate_id)];
            }

            // 店主筛选
            if ($user_id) {
                $where['user_id'] = $user_id;
            }

            // 搜索词筛选
            if ($keyword) {
                // 多个连续空格转换成一个空格
                //$keyword = explode(" ", preg_replace("/\s(?=\s)/","\\1",$keyword));

                $where['name|description|keyword'] = ['like', '%' . $keyword . '%'];
            }
            // 销量排序
            if ($sales) {
                $order['sales'] = $sales;
            }
            // 价格排序
            if ($price) {
                $order['price'] = $price;
            }
            // 浏览量排序
            if ($visit) {
                $order['visit_num'] = $visit;
            }

            //$where['delete_time'] = ['EXP', 'IS NULL'];
            $where['is_hidden'] = 0;
            $where['stock'] = ['gt', 0];
            $order['sort'] = 'desc';
            $order['id'] = 'desc';

            try {
                $data = $this->db->name('mall_goods')
                    ->field('id, image, name, description, price, postage, sales, stock, visit_num, user_id, xuni_sales, fanli, fanli_rate, fanli_day')
                    ->where($where)
                    ->order($order)
                    ->cache(false)->fetchSql(false)->paginate(10)->toarray();
            } catch (Exception $e) {
                return json(['err' => $e->getMessage()]);
            }
            $rate = 5;
            if ($data['data']) {

                $uidArr = [];
                foreach ($data['data'] as $key => $value) {
                    $data['data'][$key]['image'] = $value['image'];
                    $data['data'][$key]['sales'] = $value['sales'] + $value['xuni_sales'];

                    $uidArr[] = $value['user_id'];
                }

                $uidArr = array_unique($uidArr);
                $userArr = $this->db->name('user')->where(['id' => ['in', $uidArr]])->column('id, name, city');
                foreach ($data['data'] as $k => $v) {
                    if (array_key_exists($v['user_id'], $userArr)) {
                        $data['data'][$k]['nickname'] = $userArr[$v['user_id']]['name'];
                        $data['data'][$k]['city'] = $userArr[$v['user_id']]['city'];
                    } else {
                        $data['data'][$k]['nickname'] = null;
                        $data['data'][$k]['city'] = null;
                    }
                    if ($score) {
                        $data['data'][$k]['price'] = $v['price'] * $this->rate;
                    }

                    if ($v['fanli']) {
                        $data['data'][$k]['fanli_rate'] = $v['fanli_rate'] . '%';
                        $data['data'][$k]['fanli_year'] = $v['fanli_day'] / 365;
                    } else {
                        $data['data'][$k]['fanli_rate'] = '';
                        $data['data'][$k]['fanli_day'] = '';
                        $data['data'][$k]['fanli_year'] = '';
                    }
                }
            }

            return $returnJson ? json(['ret' => $data]) : $data;
        }
    }

    public function goodsListRecommend($returnJson = true)
    {
        if (!$this->member) return $returnJson ? $this->pass([]) : [];
        // 全局安全过滤
        Request::instance()->filter(['strip_tags', 'htmlspecialchars_decode', 'trim']);
        $score = input('score/d', 1);
        $data = [
            'page' => $page = input('page/d') ? input('page/d') : 1,
            'user_id' => $user_id = input('user_id/d'),
            'keyword' => $keyword = input('keyword'),
            'sales' => $sales = input('sales'),
            'price' => $price = input('price'),
            'visit' => $visit = input('visit'),
        ];

        // 开始验证
        $validate = new Validate([
            ['page', 'number|>:0', '分页有误|分页有误'],
            ['sales', 'in:asc,desc', '销量排序有误'],
            ['price', 'in:asc,desc', '价格排序有误'],
            ['visit', 'in:asc,desc', '浏览量排序有误'],
        ]);

        if (!$validate->check($data)) {
            exit(json_encode(['err' => $validate->getError()]));
        } else {
            $where = [];
            $order = [];
            $where = [];

            // 搜索词筛选
            if ($keyword) {
                $where['name|description|keyword'] = ['like', '%' . $keyword . '%'];
            }
            // 销量排序
            if ($sales) {
                $order['sales'] = $sales;
            }
            // 价格排序
            if ($price) {
                $order['price'] = $price;
            }
            // 浏览量排序
            if ($visit) {
                $order['visit_num'] = $visit;
            }

            //$where['delete_time'] = ['EXP', 'IS NULL'];
            $where['is_hidden'] = 0;
            $where['stock'] = ['gt', 0];
            $order['sort'] = 'desc';
            $order['id'] = 'desc';

            $sex = $this->member['sex'] ?? '';
            $age = $this->member['age'] ?? 0;

            $whereStr = '((rec_sex = "" or rec_sex="'.$sex . '") and ((rec_age_min<='.$age.' and rec_age_max>='.$age.') or (rec_age_min between 1 and '.$age.' and rec_age_max=0) or (rec_age_max>='.$age.' and rec_age_min=0))) or (rec_sex="'.$sex . '" and rec_age_min=0 and rec_age_max=0)';
            // exit($whereStr);
            try {
                $data = $this->db->name('mall_goods')
                    ->field('id, image, name, description, price, postage, sales, stock, visit_num, user_id, xuni_sales')
                    ->where($where)
                    ->where($whereStr)
                    ->order($order)
                    ->cache(false)->fetchSql(false)->paginate(10)->each(function ($item)
                    {
                        $item['image'] = _getUrlHead($item['image']);
                        return $item;
                    })->toarray();

            } catch (Exception $e) {
                return json(['err' => $e->getMessage()]);
            }
            if ($data['data']) {

                $uidArr = [];
                foreach ($data['data'] as $key => $value) {
                    $data['data'][$key]['image'] = $value['image'];
                    $data['data'][$key]['sales'] = $value['sales'] + $value['xuni_sales'];

                    $uidArr[] = $value['user_id'];
                }

                $uidArr = array_unique($uidArr);
                $userArr = $this->db->name('user')->where(['id' => ['in', $uidArr]])->column('id, name, city');
                foreach ($data['data'] as $k => $v) {
                    if (array_key_exists($v['user_id'], $userArr)) {
                        $data['data'][$k]['nickname'] = $userArr[$v['user_id']]['name'];
                        $data['data'][$k]['city'] = $userArr[$v['user_id']]['city'];
                    } else {
                        $data['data'][$k]['nickname'] = null;
                        $data['data'][$k]['city'] = null;
                    }
                    if ($score) {
                        $data['data'][$k]['price'] = $v['price'] * $this->rate;
                    }
                }
            }

            return $returnJson ? json(['ret' => $data]) : $data;
        }
    }
    // 商品详情
    public function goodsDetail()
    {
        $goods_id = input('goods_id/d');
        // $user_id = input('user_id/d');
        $user_id = $this->member_relang['id']??0;
        $score = input('score/d', 1);

        // 开始验证
        $validate = new Validate([
            ['goods_id', 'require|number|>:0', '商品有误|商品有误|商品有误'],
            ['user_id', 'number|>:0', '用户有误|用户有误'],
        ]);

        $data = [
            'goods_id' => $goods_id,
            'user_id' => $user_id,
        ];

        if (!$validate->check($data)) {
            exit(json_encode(['err' => $validate->getError()]));
        } else {
            try {
                $data = $this->db->name('mall_goods')
                    ->field('id, user_id, image, slider_image, name, description, detail, price,is_postage, postage, sales, stock, visit_num, sku, xuni_sales, sku_price,sku_stock, fanli, fanli_rate, fanli_day')
                    ->where(['id' => $goods_id, 'is_hidden' => 0])
                    ->cache(false)->fetchSql(false)->find();

            } catch (Exception $e) {
                return json(['err' => $e->getMessage()]);
            }

            if ($data) {
                // 浏览量+1
                $this->db->name('mall_goods')->where('id', $goods_id)->setInc('visit_num');

                $data['image'] = $data['image'];

                // 轮播图
                if ($data['slider_image']) {
                    $slider_image = json_decode($data['slider_image'], true);
                    foreach ($slider_image as $key => $value) {
                        $slider_image[$key] = $value;
                    }

                    $data['slider_image'] = $slider_image;
                } else {
                    $data['slider_image'] = NULL;
                }

                // 登录状态下查看是否收藏商品
                if ($user_id) {
                    $result = $this->db->name('mall_goods_favourite')->where([
                        'user_id' => $user_id,
                        'goods_id' => $goods_id,
                        //'delete_time' => ['EXP', 'IS NULL']
                    ])->find();

                    if ($result) {
                        $data['is_favourite'] = 1;
                    } else {
                        $data['is_favourite'] = 0;
                    }
                } else {
                    $data['is_favourite'] = 0;
                }

                $data['description'] = out_content($data['description']);
                $data['sku'] = $data['sku'] ? explode(',', $data['sku']) : [];
                $data['sku_price'] = $data['sku_price'] ? explode(',', $data['sku_price']) : [];
                $data['sku_stock'] = $data['sku_stock'] ? explode(',', $data['sku_stock']) : [];
                if ($score) {
                    $data['price'] = $data['price'] * $this->rate;
                }
                $data['sales'] = $data['sales'] + $data['xuni_sales'];

                $data['postage'] = $data['is_postage'] ? 0 : $data['postage'];

                if ($data['fanli']) {
                    $data['fanli_rate'] = $data['fanli_rate'] . '%';
                    $data['fanli_year'] = $data['fanli_day'] / 365;
                } else {
                    $data['fanli_rate'] = '';
                    $data['fanli_day'] = '';
                    $data['fanli_year'] = '';
                }

                return json(['ret' => $data]);
            } else {
                return json(['err' => '商品不存在或已下架']);
            }
        }
    }

    // 购物车确认订单页面
    public function cartConfirmOrder()
    {
        $uid = $this->member['id'];
        $uid_o = $this->member_relang['id'];

        // 购物车id集合
        $list = input('ids');
        if (!$list) return $this->miss('购物车选择错误');
        // 实时查询，过滤掉下架、删除商品 再提交订单
        $result = $this->db->name('mall_goods_cart t1')
            ->field("t1.id, t1.num, t1.merchant_id, t1.sku, t2.postage, t2.is_postage, t2.id goods_id, t2.name, t2.price, t2.stock, t2.image, t2.sku skus, t2.sku_price, t2.sku_stock")
            ->join('mall_goods t2', 't2.id = t1.goods_id')
            ->where([
                't1.id' => ['in', $list],
                't1.user_id' => $uid_o,
                't2.is_hidden' => 0,
            ])
            ->order('t1.id desc')
            ->select();
        if (sizeof($result) == 0) {
            return $this->miss('购物车选择错误');
        }

        // 实时判断库存是否足够
        $data = [];
        foreach ($result as $k => $v) {
            if ($v['num'] > $v['stock']) {
                return $this->miss('商品[' . $v['name'] . ']库存不足，更改购物车数量后再提交');
            }
            if ($v['sku']) {
                $skus = explode(',', $v['skus']);
                $idx = array_search($v['sku'], $skus);
                if ($idx === false) {
                    return $this->miss('部分商品失效');
                }
                $sku_price = explode(',', $v['sku_price']);
                $sku_stock = explode(',', $v['sku_stock']);
                $v['price'] = $sku_price[$idx];
                $v['stock'] = $sku_stock[$idx];
            }
            $v['image'] = $v['image'];
            $data[$v['merchant_id']][] = $v;
        }

        $contain = [];
        $totalMoney = 0;
        foreach ($data as $k => $v) {
            $num = 0;
            $total = 0;
            $postage = 0;
            foreach ($v as $m => $n) {
                /**
                 * 订单有多个商品时，总运费只统计最高运费的商品，其他商品运费作0统计
                 * 目前运费逻辑暂不使用运费模板逻辑，不同商品选择不同运费模板，有首件续件
                 */
                if (!$n['is_postage'] && $n['postage'] > $postage) {
                    $postage = $n['postage'];
                }
                // 商品总计金额
                $total += $n['price'] * $n['num'];
                // 商品数量
                $num += $n['num'];
            }
            $total = $total;
            $totalMoney += $total + $postage;

            $contain['list'][] = [
                'list' => $v,
                'merchant_id' => $n['merchant_id'],
                'postage' => $postage,
                'num' => $num,
                'money' => $total + $postage
            ];
        }
        $contain['money'] = $totalMoney;

        return $this->pass($contain);
    }


    public function cartCreateOrder($w2 = 0)
    {
        $config = Config::index('system');
        $user = $this->member;
        $uid = $user['id'];
        $uid_o = $this->member_relang['id'];

        // 购物车id集合
        $list = input('ids');
        $remark = input('remark', '');
        if (!$list) return $this->miss('商品选择有误');

        $gateway = input('gateway');
        $paymethod = input('paymethod',1);
        if (!in_array($gateway, [1, 2, 3, 5])) {
            return $this->miss('支付方式选择错误');
        }
        if ($paymethod == 3) {
            if (!in_array($paymethod, [1, 2])) {
                return $this->miss('支付通道选择错误');
            }
        }

        // 收货地址
        $address_id = input('address_id/d');
        if (!$address_id) return $this->miss('请先选择收货地址');
        
        $addressInfo = $this->db->name('mall_member_address')->where(['id' => $address_id, 'uid' => $uid_o])->find();
        if (!$addressInfo) return $this->miss('地址选择错误');

        // 实时查询，过滤掉下架、删除商品 再提交订单
        $result = $this->db->name('mall_goods_cart t1')
            ->field("t1.id, t1.num, t1.merchant_id, t1.sku, t2.postage, t2.is_postage, t2.id goods_id, t2.name, t2.price, t2.stock, t2.image, t2.sku skus, t2.sku_price, t2.sku_stock")
            ->join('mall_goods t2', 't2.id = t1.goods_id')
            ->where([
                't1.id' => ['in', $list],
                't1.user_id' => $uid_o,
                't2.is_hidden' => 0,
            ])
            ->order('t1.id desc')
            ->select();
        if (sizeof($result) == 0) {
            return $this->miss('购物车选择错误');
        }

        // 实时判断库存是否足够
        $data = [];
        $goodsList = [];
        foreach ($result as $k => $v) {
            if ($v['num'] > $v['stock']) {
                return $this->miss('商品[' . $v['name'] . ']库存不足，更改购物车数量后再提交');
            }
            if ($v['sku']) {
                $skus = explode(',', $v['skus']);
                $idx = array_search($v['sku'], $skus);
                if ($idx === false) {
                    return $this->miss('部分商品失效');
                }
                $v['sku_price'] = explode(',', $v['sku_price']);
                $v['sku_stock'] = explode(',', $v['sku_stock']);
                $v['price'] = $v['sku_price'][$idx];
                $v['sku_idx'] = $idx;
            }
            if (!isset($goodsList[$v['goods_id']])) {
                $goodsList[$v['goods_id']] = [
                    'sku_stock'=>$v['sku_stock']?:[],
                    'stock'=>$v['stock']
                ];
            }
            $goodsList[$v['goods_id']]['stock']-=$v['num'];
            if (isset($v['sku_idx'])) {
                $goodsList[$v['goods_id']]['sku_stock'][$v['sku_idx']]-=$v['num'];
                if ($goodsList[$v['goods_id']]['sku_stock'][$v['sku_idx']] < 0) {
                    return $this->miss('商品[' . $v['name'] . ']库存不足，更改购物车数量后再提交');
                }
            }
            $data[] = $v;
        }

        if ($data) {
            $current_time = time();
            $msg = '购买商品';
            // 启动事务
            Db::startTrans();
            try {
                $totalMoney = 0;
                $orderIdList = [];
                $postage = 0;
                $total = 0;
                $arr = [];

                foreach ($data as $k => $v) {
                    /**
                     * 订单有多个商品时，总运费只统计最高运费的商品，其他商品运费作0统计
                     * 目前运费逻辑暂不使用运费模板逻辑，不同商品选择不同运费模板，有首件续件
                     */
                    if (!$v['is_postage'] && $v['postage'] > $postage) {
                        $postage = $v['postage'];
                    }
                    // 商品总计金额
                    $total += $v['price'] * $v['num'];
                    // 订单详细
                    $arr[] = [
                        'order_id' => '',
                        'goods_id' => $v['goods_id'],
                        'num' => $v['num'],
                        'price' => $v['price'],
                        'create_time' => $current_time,
                        'update_time' => $current_time,
                        'sku'         => $v['sku'],
                    ];
                }
                foreach ($goodsList as $goodsListkey => $goodsListvalue) {
                    $goodsListvalue['sku_stock'] = implode(',', $goodsListvalue['sku_stock']);
                    if ($goodsListvalue['stock'] == 0) {
                        // 订单数量达到库存，减去库存以及自动下架商品
                        $goodsListvalue['is_hidden'] = 1;
                    }
                    $this->db->name('mall_goods')->where('id', $goodsListkey)->update($goodsListvalue);
                }
                $rate = 5;
                $totalMoney = $postage + $total;
                $totalMoneyToScore = $totalMoney * $rate;

                // 抵扣总金额
                $dikou_money = 0;
                // 扣除积分
                $des_score = 0;
                // 扣除金币
                $des_volley = 0;
                // 需支付金额
                $pay_money = 0;
                switch (intval($gateway)) {
                    case 1:
                        if ($user['realname_auth'] != 2) {
                            return $this->miss('您未实名认证');
                        }
                        // if ($user['score'] < $totalMoneyToScore) {
                        //     return $this->miss('积分不足以抵扣');
                        // }
                        // $dikou_money = $des_score = $totalMoneyToScore;
                        $des_total = $totalMoneyToScore;
                        if ($user['score'] > 0 && $des_total) {
                            if ($user['score'] > $des_total) {
                                $des_score = $des_total;
                                $des_total = 0;
                            } else {
                                $des_total = $des_total - $user['score'];
                                $des_score = $user['score'];
                            }
                        }
                        $dikou_money = $des_score;
                        $pay_money = $totalMoneyToScore - $dikou_money;
                        break;
                    case 2:
                        // if ($user['volley'] < $totalMoneyToScore * $config['rate_volley_mall']) {
                        //     return $this->miss('金币不足以抵扣');
                        // }
                        // $des_volley = $totalMoneyToScore * $config['rate_volley_mall'];
                        // $dikou_money = $totalMoneyToScore;
                        $des_total = $totalMoneyToScore;
                        if ($user['volley'] > 0) {
                            if ($user['volley'] > $des_total * $config['rate_volley_mall']) {
                                $des_volley = $des_total * $config['rate_volley_mall'];
                                $des_total = 0;
                            } else {
                                $des_total = $des_total - $user['volley'] / $config['rate_volley_mall'];
                                $des_volley = $user['volley'];
                            }
                        }
                        $dikou_money = $des_volley / $config['rate_volley_mall'];
                        $pay_money = $totalMoneyToScore - $dikou_money;
                        break;
                    case 3:
                        return $this->miss('只允许金币或者积分兑换');
                        // 剩余待支付
                        $des_total = $totalMoneyToScore;
                        if ($user['volley'] > 0) {
                            if ($user['volley'] > $des_total * $config['rate_volley_mall']) {
                                $des_volley = $des_total * $config['rate_volley_mall'];
                                $des_total = 0;
                            } else {
                                $des_total = $des_total - $user['volley'] / $config['rate_volley_mall'];
                                $des_volley = $user['volley'];
                            }
                        }
                        if ($user['score'] > 0 && $des_total) {
                            if ($user['realname_auth'] != 2) {
                                return $this->miss('您未实名认证');
                            }
                            if ($user['score'] > $des_total) {
                                $des_score = $des_total;
                                $des_total = 0;
                            } else {
                                $des_total = $des_total - $user['score'];
                                $des_score = $user['score'];
                            }
                        }
                        // 抵扣总金额
                        $dikou_money = $des_volley / $config['rate_volley_mall'] + $des_score;
                        // 剩余待支付
                        $pay_money = $totalMoneyToScore - $dikou_money;
                        break;
                    case 5:
                        $des_score = 0;
                        $des_volley = 0;
                        $dikou_money = 0;
                        $pay_money = $totalMoneyToScore;
                        break;
                }

                $orderArr = [
                    'number' => uniqid('mc'),
                    'uid' => $uid_o,
                    'merchant_id' => 0,
                    'total' => $totalMoney,
                    'postage' => $postage,
                    'money' => number_format($pay_money ? $pay_money / $rate : 0, 2),
                    'remark' => $remark,
                    'address' => json_encode([
                        'receiver' => $addressInfo['receiver'],
                        'mobile' => $addressInfo['mobile'],
                        'area' => $addressInfo['area'],
                        'address' => $addressInfo['address']
                    ], JSON_UNESCAPED_UNICODE),
                    'create_time' => $current_time,
                    'expire_time' => $current_time + 30 * 60, // 订单有效时间
                    'paymethod'   => $paymethod,
                    'gateway'     => $gateway,
                    'dikou'     => number_format($dikou_money, 2),
                    'des_rate'  => $rate,
                    'des_score' => $des_score,
                    'des_volley' => $des_volley,
                    'types'     => 1
                ];
                $orderArr['id'] = $order_id = $this->db->name('mall_order')->insertGetId($orderArr);


                foreach ($arr as $k => $v) {
                    $arr[$k]['order_id'] = $order_id;
                }
                // 订单详细
                $this->db->name('mall_order_item')->insertAll($arr);

                // 购物车商品删除
                $this->db->name('mall_goods_cart')->where(['id' => ['in', $list]])->delete();


                // if ($gateway == 1) {
                //     Db::name('mall_order')->where('id', $order_id)->update(['status' => 1, 'charge_time' => time()]);
                //     YaoqingRecords::index($uid, 0, $des_score, $msg . ' no.' . $orderArr['number'], 1, '', 1);
                //     MallDistribution::Add($order_id);
                // } else if ($gateway == 2) {
                //     Db::name('mall_order')->where('id', $order_id)->update(['status' => 1, 'charge_time' => time()]);
                //     Balance::index($uid, $des_volley, $msg . ' no.' . $orderArr['number']);
                //     MallDistribution::Add($order_id);
                // } else if ($gateway == 3) {
                    if ($des_volley) {
                        Balance::index($uid, $des_volley, $msg . ' no.' . $orderArr['number']);
                    }
                    if ($des_score) {
                        YaoqingRecords::index($uid, 0, $des_score, $msg . ' no.' . $orderArr['number'], 1, '', 1);
                    }
                    if ($orderArr['money'] == 0) {
                        $this->db->name('mall_order')->where('id', $order_id)->update(['status' => 1, 'charge_time' => time()]);
                        MallDistribution::Add($order_id);
                        MallOrderFanli::Add($order_id);
                    } else {
                        if (input('h5', 0)) {
                        } else {
                            $pays = ['api/alipay/tradeAppPay', 'api/wechat/app'];
                            $paymethods = $pays[$paymethod - 1];
                            if ($w2 && $paymethods == 'api/wechat/app') {
                                $paymethods = 'api/wechat2/app';
                            }
                            $orders = action($paymethods, ['order_sn' => $orderArr['number'], 'total_amount' => number_format($orderArr['money'],2), 'returnJson'=>false]);
                            $orderArr['url'] = $orders;
                        }
                    }
                // }
                // 提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                return $this->miss($e->getMessage());
            }

            if (input('h5', 0)) {
                return $this->pass(['order_sn' => $orderArr['number'], 'url' => 'api/wap/pay']);
            }
            
            return $this->pass($orderArr);
        } else {
            return $this->miss('请先选择商品');
        }
    }

    // 直接购买确认订单页面
    public function directConfirmOrder()
    {
        // 全局安全过滤
        Request::instance()->filter(['strip_tags', 'htmlspecialchars_decode', 'trim']);

        /*$this->checkToken();

        $uid = $this->member['id'];*/

        $uid = $this->member['id'];
        $uid_o = $this->member_relang['id'];

        $goods_id = input('goods_id/d');
        $num = input('num/d') ? input('num/d') : 1;

        // 开始验证
        $validate = new Validate([
            ['goods_id', 'require|>:0', '请先选择商品|商品有误'],
            ['num', '>:0', '数量有误'],
        ]);

        $data = [
            'goods_id' => $goods_id,
            'num' => $num,
        ];

        if (!$validate->check($data)) {
            exit(json_encode(['err' => $validate->getError()]));
        } else {
            // 实时查询，过滤掉下架、删除商品 再提交订单
            $goods = $this->db->name('mall_goods')
                ->field("id, user_id, postage, is_postage, name, price, stock, image")
                ->where([
                    'id' => $goods_id,
                    'is_hidden' => 0,
                    //'delete_time' => ['EXP', 'IS NULL'],
                ])
                ->find();

            // 实时判断库存是否足够
            if ($num > $goods['stock']) {
                return json(['err' => 'id:' . $goods['id'] . '商品[' . $goods['name'] . ']库存不足，更改数量后再提交']);
            }
            $goods['image'] = $goods['image'];

            // 运费
            $postage = $goods['is_postage'] ? 0 : $goods['postage'];

            // 商品总计金额
            $total = $goods['price'] * $num;

            $data = [
                'list' => [[
                    'list' => [$goods],
                    'merchant_id' => $goods['user_id'],
                    'postage' => $postage,
                    'num' => $num,
                    'money' => number_format(($total + $postage), 2)
                ]],
                'money' => number_format(($total + $postage), 2)
            ];

            return json(['ret' => $data]);
        }
    }

    // 直接购买提交订单
    public function directCreateOrder($w2 = 0)
    {
        // 全局安全过滤
        Request::instance()->filter(['strip_tags', 'htmlspecialchars_decode', 'trim']);

        /*$this->checkToken();

        $uid = $this->member['id'];*/

        $user = $this->member;
        $uid = $this->member['id'];
        $uid_o = $this->member_relang['id'];

        $goods_id = input('goods_id');
        $num = input('num') ?: 1;
        $address_id = input('address_id/d');
        $remark = input('remark') ?: '';
        $gateway = input('gateway') ?: 1;
        $paymethod = input('paymethod/d', 1);
        // $dikou = input('dikou') || 0;
        $to_user = input('to_user/d') ?: 0;
        $ios = input('ios/d', 0);
        $sku = input('sku', '');

        // 修改支付方式
        // 1积分 2金币 3组合支付（优先使用积分金币，不足时需额外支付，提交时一并提交支付方式）
        // paymethod // 1支付宝 2微信
        // 开始验证
        $validate = new Validate([
            ['goods_id', 'require|>:0', '请先选择商品|商品有误'],
            ['num', '>:0', '数量有误'],
            // ['address_id', '>:0', '收货地址有误'],
            ['gateway', 'in:1,2,3,5', '付款方式有误'],
        ]);

        $data = [
            'goods_id' => $goods_id,
            'num' => $num,
            'address_id' => $address_id,
            'gateway' => $gateway,
        ];

        if (!$validate->check($data)) {
            exit(json_encode(['err' => $validate->getError()]));
        } else {
            if (!$to_user) {
                $addressInfo = $this->db->name('mall_member_address')->where(['id' => $address_id, 'uid' => $uid_o])->find();
                if (!$addressInfo) return json(['err' => '地址选择错误']);
            }
            
            // 实时查询，过滤掉下架、删除商品 再提交订单
            $goods = $this->db->name('mall_goods')
                ->field("id, name, user_id, image, postage, is_postage, price, stock, sku, sku_price, sku_stock")
                ->where([
                    'id' => $goods_id,
                    'is_hidden' => 0,
                    //'delete_time' => ['EXP', 'IS NULL'],
                ])
                ->find();

            if (!$data) return json(['err' => '商品不存在或已下架']);

            if ($goods['sku']) {
                $skus = explode(',', $goods['sku']);
                $idx = array_search($sku, $skus);
                if ($idx === false) {
                    return $this->miss('商品失效');
                }
                $sku_price = $goods['sku_price']?explode(',', $goods['sku_price']):[];
                $sku_stock = $goods['sku_stock']?explode(',', $goods['sku_stock']):[];
                $goods['price'] = $sku_price[$idx]??$goods['price'];
                $goods['stock'] = $sku_stock[$idx]??$goods['stock'];
            }

            // 实时判断库存是否足够
            if ($num > $goods['stock']) {
                return json(['err' => 'id:' . $goods['id'] . '商品[' . $goods['name'] . ']库存不足，更改数量后再提交']);
            }

            $to_user_o = $to_user;
            if ($to_user && $to_user != $uid) {
                $to_user_o = _channelUser($to_user)['id'];
                $types = 2;
                $msg = '兑换赠送礼物';
            } else {
                $types = 1;
                $msg = '兑换商品';
            }
    
            $image = $goods['image'];
            $goods['image'] = $goods['image'];

            // 运费
            $postage = $goods['is_postage'] ? 0 : $goods['postage'];

            // 商品总计金额
            $total = $goods['price'] * $num + $postage;

            $frozen = Db::name('wallet_frozen')->where(['user_id'=>$uid])->find();
            if($frozen){
                $user['score'] = $user['score'] - $frozen['value'];
            }

            // 兑换比例
            $rate = 5;
            // 商品总计金额
            $totalToScore = $total * $rate;
            $config = Db::name('config_system')->column('title,content');
            // 抵扣总金额
            $dikou_money = 0;
            // 扣除积分
            $des_score = 0;
            // 扣除金币
            $des_volley = 0;
            // 需支付金额
            $pay_money = 0;
            switch (intval($gateway)) {
                case 1:
                    if ($user['realname_auth'] != 2) {
                        return $this->miss('您未实名认证');
                    }
                    // if ($user['score'] < $totalToScore) {
                    //     return json(['err' => '积分不足以抵扣']);
                    // }
                    // Db::name('user')->where(['id' => $uid])->setDec('score', $total);
                    // $dikou_money = $des_score = $totalToScore;
                    $des_total = $totalToScore;
                    if ($user['score'] > 0 && $des_total) {
                        if ($user['realname_auth'] != 2) {
                            return $this->miss('您未实名认证');
                        }
                        if ($user['score'] > $des_total) {
                            $des_score = $des_total;
                            $des_total = 0;
                        } else {
                            $des_total = $des_total - $user['score'];
                            $des_score = $user['score'];
                        }
                    }
                    // 抵扣总金额
                    $dikou_money = $des_score;
                    // 剩余待支付
                    $pay_money = $totalToScore - $dikou_money;
                    break;
                case 2:
                    // if ($user['volley'] < $totalToScore * $config['rate_volley_mall']) {
                    //     return json(['err' => '金币不足以抵扣']);
                    // }
                    // Db::name('user')->where(['id' => $uid])->setDec('volley', $total);
                    // $des_volley = $totalToScore * $config['rate_volley_mall'];
                    // $dikou_money = $totalToScore;
                    
                    $des_total = $totalToScore;
                    if ($user['volley'] > 0) {
                        if ($user['volley'] > $des_total * $config['rate_volley_mall']) {
                            $des_volley = $des_total * $config['rate_volley_mall'];
                            $des_total = 0;
                        } else {
                            $des_total = $des_total - $user['volley'] / $config['rate_volley_mall'];
                            $des_volley = $user['volley'];
                        }
                    }
                    // 抵扣总金额
                    $dikou_money = $des_volley / $config['rate_volley_mall'];
                    // 剩余待支付
                    $pay_money = $totalToScore - $dikou_money;
                    break;
                case 3:
                    return $this->miss('只允许金币或者积分兑换');
                    // 剩余待支付
                    $des_total = $totalToScore;
                    if ($user['volley'] > 0) {
                        if ($user['volley'] > $des_total * $config['rate_volley_mall']) {
                            $des_volley = $des_total * $config['rate_volley_mall'];
                            $des_total = 0;
                        } else {
                            $des_total = $des_total - $user['volley'] / $config['rate_volley_mall'];
                            $des_volley = $user['volley'];
                        }
                    }
                    if ($user['score'] > 0 && $des_total) {
                        if ($user['realname_auth'] != 2) {
                            return $this->miss('您未实名认证');
                        }
                        if ($user['score'] > $des_total) {
                            $des_score = $des_total;
                            $des_total = 0;
                        } else {
                            $des_total = $des_total - $user['score'];
                            $des_score = $user['score'];
                        }
                    }
                    // 抵扣总金额
                    $dikou_money = $des_volley / $config['rate_volley_mall'] + $des_score;
                    // 剩余待支付
                    $pay_money = $totalToScore - $dikou_money;
                    if ($ios && $pay_money > 0) {
                        return $this->miss('积分金币总和不足以抵扣');
                    }
                    break;
                case 5:
                    $pay_money = $totalToScore;
                    $dikou_money = 0;
                    $des_score = 0;
                    $des_volley = 0;
                    break;
            }
            

            $current_time = time();

            // 启动事务
            Db::startTrans();
            try {
                $orderArr = [
                    'number' => 'mg'.uniqid(),
                    'uid' => $uid_o,
                    'merchant_id' => $goods['user_id'],
                    'total' => $total - $postage,
                    'postage' => $postage,
                    'money' => number_format($pay_money ? $pay_money / $rate : 0, 2),
                    'dikou' => number_format($dikou_money, 2),
                    'des_score' => $des_score,
                    'des_volley' => $des_volley,
                    'paymethod' => $paymethod,
                    'gateway' => $gateway,
                    'remark' => $remark,
                    'types' => $types,
                    'to_user' => $to_user_o,
                    'des_rate' => $rate,
                    'create_time' => $current_time,
                    //'expire_time' => $current_time + config('mall.order_expire') * 60, // 订单有效时间
                    'expire_time' => $current_time + 30 * 60, // 订单有效时间
                ];
                
                if ($types == 1 || $types == 3) {
                    $orderArr['address'] = json_encode([
                        'receiver' => $addressInfo['receiver'],
                        'mobile' => $addressInfo['mobile'],
                        'area' => $addressInfo['area'],
                        'address' => $addressInfo['address']
                    ], JSON_UNESCAPED_UNICODE);
                }
                
                $order_id = $this->db->name('mall_order')->insertGetId($orderArr);
                $orderArr['id'] = $order_id;
                $this->db->name('mall_order_item')->insert([
                    'order_id' => $order_id,
                    'goods_id' => $goods_id,
                    'num' => $num,
                    'sku' => $sku,
                    'price' => $goods['price'],
                    'create_time' => $current_time,
                    'update_time' => $current_time,
                ]);

                if (isset($sku_stock) && !empty($sku_stock)) {
                    $sku_stock[$idx] -= $num;
                    $goodsUpdate['stock'] = array_sum($sku_stock);
                    $goodsUpdate['sku_stock'] = implode(',', $sku_stock);
                    if ($goodsUpdate['stock'] <= 0) {
                        $goodsUpdate['is_hidden'] = 0;
                    }
                    $this->db->name('mall_goods')->where('id', $goods_id)->update($goodsUpdate);
                } else if ($num >= $goods['stock']) {
                    // 订单数量达到库存，减去库存以及自动下架商品
                    $this->db->name('mall_goods')->where('id', $goods_id)->update(['is_hidden' => 1, 'stock' => 0]);
                } else {
                    // 减去订单数量对应的库存
                    $this->db->name('mall_goods')->where('id', $goods_id)->update(['stock'=>Db::raw('stock-'.$num)]);
                }

                // if ($gateway == 1) {
                //     Db::name('mall_order')->where('id', $order_id)->update(['status' => 1, 'charge_time' => time()]);
                //     YaoqingRecords::index($uid, $to_user, $des_score, $msg . ' no.' . $orderArr['number'], 1, '', 1);
                //     MallDistribution::Add($order_id);
                // } else if ($gateway == 2) {
                //     Db::name('mall_order')->where('id', $order_id)->update(['status' => 1, 'charge_time' => time()]);
                //     Balance::index($uid, $des_volley, $msg . ' no.' . $orderArr['number']);
                //     MallDistribution::Add($order_id);
                // } else if ($gateway == 3) {
                    if ($des_volley) {
                        Balance::index($uid, $des_volley, $msg . ' no.' . $orderArr['number']);
                    }
                    if ($des_score) {
                        YaoqingRecords::index($uid, $to_user, $des_score, $msg . ' no.' . $orderArr['number'], 1, '', 1);
                    }
                    if ($orderArr['money'] == 0) {
                        $this->db->name('mall_order')->where('id', $order_id)->update(['status' => 1, 'charge_time' => time()]);
                        MallDistribution::Add($order_id);
                        MallOrderFanli::Add($order_id);
                    } else {
                        if (input('h5', 0)) {
                        } else {
                            $pays = ['api/alipay/tradeAppPay', 'api/wechat/app'];
                            $paymethods = $pays[$paymethod - 1];
                            if ($w2 && $paymethods == 'api/wechat/app') {
                                $paymethods = 'api/wechat2/app';
                            }
                            $orders = action($paymethods, ['order_sn' => $orderArr['number'], 'total_amount' => number_format($orderArr['money'],2), 'returnJson'=>false]);
                            $orderArr['url'] = $orders;
                        }
                    }
                // }
   
                // 提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                return json(['err' => $e->getMessage()]);
            }

            // 支付完才能发给对方
            if ($types == 2 && $orderArr['money'] == 0) {

                $request = request();
                $url = $request->domain() . str_replace('/index.php', '', $request->baseFile()) . '/apis/home/privatechat/addtalk';

                $mallRecords = $this->db->name('mall_records')->where(['user_id' => $uid_o, 'to_user' => $to_user_o, 'goods_id' => $goods_id])->find();
                if ($mallRecords) {
                    $this->db->name('mall_records')->where(['id' => $mallRecords['id']])->setInc('num', $num);
                } else {
                    $this->db->name('mall_records')->insert(['user_id' => $uid_o, 'to_user' => $to_user_o, 'goods_id' => $goods_id, 'num' => $num, 'create_time' => time(), 'update_time' => time()]);
                }

                $datas = [
                    'from' => input('from', 1),
                    'userid' => $uid,
                    'touserid' => $to_user,
                    'type' => 18,
                    'content' => '[礼物]',
                    'data' => json_encode(['order_id' => $order_id, 'name' => $goods['name'], 'image' => $image, 'num' => $num, 'money' => $orderArr['total']], JSON_UNESCAPED_UNICODE)
                ];
                
                $result = curl($url, json_encode($datas, JSON_UNESCAPED_UNICODE));
            }

            if (input('h5', 0)) {
                return json(['ret' => ['order_sn' => $orderArr['number'], 'url' => 'api/wap/pay']]);
            }
            
            return json(['ret' => $orderArr]);
        }
    }

}
